/**
 * @file mRjson.c
 * @Synopsis  简易json解析库
 * @author Wang Jiancong
 * @version v0.2
 * @date 2022-11-22
 */

#include "mRjson.h"
#include "stdarg.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wctype.h>

#define KEY_NAME_LIMIT 				200
#define JSON_LENGTH_LIMIT 			60000


enum{
	ERROR_NONE,
	ERROR_UNDEFINE 	
};
#define mRprintf 	 						printf

#ifdef mR_DBUG
#define errInit() 							unsigned int errCnt = 0;
#define errReset() 							{errCnt = 0;}
#define errPorossReturn0(limit,errCode) 	{errCnt++;if(errCnt>limit){mRprintf("\r\n!!!ERROR CODE: %d\r\n",errCode);return 0;}}
#define errPorossReturnVoid(limit,errCode) 	{errCnt++;if(errCnt>limit){mRprintf("\r\n!!!ERROR CODE: %d\r\n",errCode);return;}}
#else
#define errInit() 							
#define errReset() 							
#define errPorossReturn0(limit,errCode) 	
#define errPorossReturnVoid(limit,errCode) 	
#endif

static void cpy_str(char* str_dst, char* str_src, char ch);
static char* jumpGroup(char* ss);
static char* findFristKey(char* ss);
static char* nextBrotherKey(char* ss);

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  按指定格式输入json字符串，键，解析目标，保存结果
 * 				("%j,%i,%t,%r")
 *
 * @Param str
 * @Param ...
 */
/* --------------------------------------------------------------------------*/
void mRjson_Decode(const char *str, ...)
{
	unsigned char subTemp, i;
	errInit();
	va_list ap;

	char* jstr = NULL; 	//获取被解析的json字符
	char* istr = NULL; 	//子项
	char* tstr = NULL; 	//被解析成的目标类型
	char* nstr = NULL; 	//数组下表
	char* gstr = NULL; 	//对象键

	char* strp = NULL; 	//临时定位指针

	void* res = NULL; 	//存放解析结果
	
	va_start(ap, str);

	for(;*str;str++)
	{
		if(*str == '%')
		{
			switch (*++str) 
			{
				case 'a':
				case 'A':
					nstr = va_arg(ap, char*); 
					subTemp = atoi(nstr); 			//取出下标
					errReset();
					for(i = 0; i < subTemp; i++)
					{
						strp = jumpGroup(strp);
						errPorossReturnVoid(10000,ERROR_UNDEFINE);
					}
					strp = findFristKey(strp);
					break;
				case 'g':
				case 'G':
					gstr = va_arg(ap, char*); 
					strp += strlen(gstr) + 1;
					strp = findFristKey(strp);
					errReset();
					while (strncmp(strp, gstr, strlen(gstr)) != 0) {
						strp = nextBrotherKey(strp);
						errPorossReturnVoid(10000,ERROR_UNDEFINE);
					}
					break;
				case 'j': 
				case 'J':
					jstr = va_arg(ap, char*);
					strp = findFristKey(jstr);
					break;
				case 'i':
				case 'I':
					istr = va_arg(ap, char*);
					errReset();
					while (strncmp(strp, istr, strlen(istr)) != 0) {
						strp = nextBrotherKey(strp);
						errPorossReturnVoid(10000,ERROR_UNDEFINE);
					}
					break;
				case 't':
				case 'T':
					tstr = va_arg(ap, char*);
					break;
				case 'r':
				case 'R':
					errReset();
					while (*strp!= ':') { 	//跳过键名部分, 指向冒号
						strp ++;
						errPorossReturnVoid(10000,ERROR_UNDEFINE);
					}
					errReset();
					while (*strp == ' ' || 	//指向键值
							*strp == ':' ||
							*strp == '"') 
					{
						strp ++;
						errPorossReturnVoid(10000,ERROR_UNDEFINE);
					}

					switch (*tstr) {
						case 'd':
						case 'D':
							res = va_arg(ap, int*);
							*(int*)res = atoi(strp);
							break;
						case 'f':
						case 'F':
							res = va_arg(ap, double*);
							*(double*)res = atof(strp);
							break;
						case 's':
						case 'S':
							res = va_arg(ap, char*);
							memset(res, 0, strlen((char*)res)); 	//清空保存缓冲

							cpy_str(res, strp, '"');
							break;
					}
					break;
			}
		}
	}
	va_end(ap);
}

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  拷贝字符串直到遇到指定字符
 *
 * @Param str_dst 目标字符串
 * @Param str_src 源字符串, 被拷贝
 * @Param ch 指定字符
 */
/* --------------------------------------------------------------------------*/
static void cpy_str(char* str_dst, char* str_src, char ch)
{
	errInit();
	while (*str_src != ch) {
		*str_dst ++ = *str_src++;
		errPorossReturnVoid(60000,ERROR_UNDEFINE);
	}
}

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  跳过一次对象
 *
 * @Param ss 对象键名地址
 *
 * @Returns  对象后的起始地址
 */
/* --------------------------------------------------------------------------*/
static char* jumpGroup(char* ss)
{
	errInit();
	char* ssTemp = ss;
	unsigned char bBcnt = 0;
	unsigned char fb = 1;
	while (fb == 1 || bBcnt) {
		if(*ssTemp == '{')
		{
			fb = 0;
			bBcnt ++;
		}
		if(*ssTemp == '}')
			bBcnt --;
		ssTemp ++;
		errPorossReturn0(JSON_LENGTH_LIMIT,ERROR_UNDEFINE);
	}	
	return ++ssTemp;
}

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  定位第一个键
 *
 * @Param ss
 *
 * @Returns   
 */
/* --------------------------------------------------------------------------*/
static char* findFristKey(char* ss)
{
	errInit();
	char* ssTemp = ss;
	while (*ssTemp != '"') {
		ssTemp ++;
		errPorossReturn0(JSON_LENGTH_LIMIT,ERROR_UNDEFINE);
	}
	return ++ssTemp;
}

/* --------------------------------------------------------------------------*/
/**
 * @Synopsis  定位下一个同层级键
 *
 * @Param ss
 *
 * @Returns   
 */
/* --------------------------------------------------------------------------*/
static char* nextBrotherKey(char* ss)
{
	errInit();
	char* ssTemp = ss;
	unsigned char mBcnt = 0;
	unsigned char bBcnt = 0;
	while (*ssTemp != ',' || mBcnt || bBcnt) {
		if(*ssTemp == '{')
			bBcnt ++;
		if(*ssTemp == '}')
			bBcnt --;
		if(*ssTemp == '[')
			mBcnt ++;
		if(*ssTemp == ']')
			mBcnt --;
		ssTemp ++;
		errPorossReturn0(JSON_LENGTH_LIMIT,ERROR_UNDEFINE);
	}
	ssTemp = findFristKey(ssTemp);
	return ssTemp;
}



